using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using NUnit.Framework;

using NHibernate.Hql;
using NHibernate.Criterion;

using Castle.ActiveRecord;
using Castle.ActiveRecord.Queries;
using Castle.ActiveRecord.Framework;
using Castle.ActiveRecord.Framework.Config;

using Demo.Model;
using Pampa.CRUD.Core;


namespace Demo.Model.Test
{
    [TestFixture]
    public class HqlTestCase : AbstractModelTestCase
    {
        [SetUp]
        public override void Init()
        {
            base.Init();

            Demo.Model.Utils.DataManager.FillTestData();
        }

        [Test]
        public void Nested_Properties_Detached_Criteria()
        {
            DetachedCriteria cd = DetachedCriteria.For(typeof(Customer))
                .CreateCriteria("Nationality")
                .Add(Expression.Eq("Description", "Argentina")); 

            Customer[] customers = Customer.FindAll(cd);
            Assert.AreEqual(10, customers.Length);
        }

        [Test]
        public void Nested_Properties_Hql()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer), "select c from Customer c where c.Nationality.Description = 'Argentina'");
            Customer[] customers = customerQuery.Execute();
            Assert.AreEqual(10, customers.Length);
        }

        [Test]
        public void Nested_Properties_Exists_Using_In_Elements()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer),
                "select c from Customer c, Hobby h where h in elements(c.Hobbies) and h.Description = 'Drums'");

            Customer[] customers = customerQuery.Execute();

            foreach (Customer customer in customers)
            {
                Console.WriteLine(customer.FirstName + ", " + customer.LastName);
            }

            Assert.AreEqual(2, customers.Length);
        }

        [Test]
        public void Nested_Properties_Exists_Using_Explicit_Joins()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer),
                "select distinct c from Customer c join c.Hobbies as h where h.Description = 'Drums'");

            Customer[] customers = customerQuery.Execute();

            foreach (Customer customer in customers)
            {
                Console.WriteLine(customer.FirstName + ", " + customer.LastName);
            }

            Assert.AreEqual(2, customers.Length);
        }

        [Test]
        public void Nested_Properties_Exists_Using_Explicit_Joins_Advanced()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer),
                "select distinct c from Customer c join c.Hobbies as h where h.Description = 'Drums' or h.Description = 'Basketball'");

            Customer[] customers = customerQuery.Execute();

            foreach (Customer customer in customers)
            {
                Console.WriteLine(customer.FirstName + ", " + customer.LastName);
            }

            Assert.AreEqual(2, customers.Length);
        }

        [Test]
        public void Nested_Properties_Hql_Using_IEntity()
        {
            SimpleQuery<IActiveRecord> customerQuery = new SimpleQuery<IActiveRecord>(typeof(Customer),
                "select c from Customer c where c.Address.City.Description = 'Lomas de Zamora'");

            IActiveRecord[] customers = customerQuery.Execute();
            Assert.AreEqual(10, customers.Length);
        }

        [Test]
        public void Nested_Properties_Hql_UsingIEntity_And_Parameters()
        {
            SimpleQuery<IActiveRecord> customerQuery = new SimpleQuery<IActiveRecord>(typeof(Customer),
                "Select Cus FROM Customer Cus WHERE ((Cus.Nationality.Description = :Nationality.Description1))");
            customerQuery.SetParameter("Nationality.Description1", "Argentina");

            IActiveRecord[] customers = customerQuery.Execute();
            Assert.AreEqual(10, customers.Length);
        }

        [Test]
        public void Nested_Properties_Exists_Using_Explicit_Joins_With_Parameters()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer),
                "SELECT distinct Cus FROM Customer Cus join Cus.Hobbies as Hob WHERE (((Hob.Description = :Description1) OR (Hob.Description = :Description2))) ORDER BY");

            customerQuery.SetParameter("Description1", "Drums");
            customerQuery.SetParameter("Description2", "Basketball");

            Customer[] customers = customerQuery.Execute();

            foreach (Customer customer in customers)
            {
                Console.WriteLine(customer.FirstName + ", " + customer.LastName);
            }

            Assert.AreEqual(2, customers.Length);
        }

        [Test]
        public void Nested_Properties_Exists_Using_Different_Types_of_Joins()
        {
            SimpleQuery<Customer> customerQuery = new SimpleQuery<Customer>(typeof(Customer),
                "SELECT distinct Cus FROM Customer c where exists(select h.id from Hobbies as h in c.Hobbies and h.Description = :Description)");

            customerQuery.SetParameter("Description", "Drums");

            Customer[] customers = customerQuery.Execute();

            Assert.AreEqual(2, customers.Length);
        }

        [Test]
        public void Entity_Properties_Hql()
        {
            Country argentina = Country.FindAllByProperty("Description", "Argentina")[0];

            SimpleQuery<IActiveRecord> customerQuery = new SimpleQuery<IActiveRecord>(typeof(Customer),
                "Select Cus FROM Customer Cus WHERE Cus.Nationality = :Nationality1");
            
            customerQuery.SetParameter("Nationality1", argentina);

            IActiveRecord[] customers = customerQuery.Execute();
            Assert.AreEqual(10, customers.Length);
        }

        [Test]
        public void Count_Entities_Hql()
        {
            Country argentina = Country.FindAllByProperty("Description", "Argentina")[0];

            ScalarQuery<long> countQuery = new ScalarQuery<long>(typeof(Customer),
                "select count(Cus) FROM Customer Cus WHERE Cus.Nationality = :Nationality1");

            countQuery.SetParameter("Nationality1", argentina);

            Assert.AreEqual(10, countQuery.Execute());
        }

        [Test]
        public void Complex_Hql_1()
        {
            SimpleQuery<IActiveRecord> customerQuery = new SimpleQuery<IActiveRecord>(typeof(Customer),
                "select Cus FROM Customer Cus left join Cus.Hobbies as Hob  WHERE ((Cus.FirstName LIKE '%0%') OR ((Hob = :hobby1) OR (Hob = :hobby2)))");

            customerQuery.SetParameter("hobby1", Hobby.FindAllByProperty("Description", "Drums")[0]);
            customerQuery.SetParameter("hobby2", Hobby.FindAllByProperty("Description", "Basketball")[0]);

            IActiveRecord[] customers1 = customerQuery.Execute();

            SimpleQuery<IActiveRecord> customerQuery2 = new SimpleQuery<IActiveRecord>(typeof(Customer),
                "select Cus FROM Customer Cus WHERE (Cus.FirstName LIKE '%0%')");
            
            IActiveRecord[] customers2 = customerQuery2.Execute();

            Assert.Greater(customers1.Length, customers2.Length);
            Console.WriteLine("Count hobbies plus name contains 0: " + customers1.Length);
            Console.WriteLine("Count hobbies name contains 0: : " + customers2.Length);
        }
    }
}
 